/* Mesquite source code.  Copyright 1997 and onward, W. Maddison and D. Maddison. 


Disclaimer:  The Mesquite source code is lengthy and we are few.  There are no doubt inefficiencies and goofs in this code. 
The commenting leaves much to be desired. Please approach this source code with the spirit of helping out.
Perhaps with your help we can be more than a few, and make Mesquite better.

Mesquite is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
Mesquite's web site is http://mesquiteproject.org

This source code and its compiled class files are free and modifiable under the terms of 
GNU Lesser General Public License.  (http://www.gnu.org/copyleft/lesser.html)
*/
package mesquite.molec.GenBankNumber;

import mesquite.categ.lib.*;
import mesquite.lists.lib.*;

import mesquite.lib.*;
import mesquite.lib.characters.CharacterData;
import mesquite.lib.characters.MCharactersDistribution;
import mesquite.lib.duties.MatrixSourceCoord;
import mesquite.lib.table.*;


/* ======================================================================== */
public class GenBankNumber extends TaxonListAssistant {
	Taxa taxa;
	MesquiteTable table=null;
	Taxa currentTaxa = null;
	MolecularData data = null;
	MatrixSourceCoord matrixSourceTask;
	MesquiteMenuItemSpec mss2;
	/*.................................................................................................................*/
	public boolean startJob(String arguments, Object condition, boolean hiredByName) {
		matrixSourceTask = (MatrixSourceCoord)hireCompatibleEmployee(MatrixSourceCoord.class, DNAState.class, "Source of DNA matrix (for " + getName() + ")"); 
		if (matrixSourceTask==null)
			return sorry(getName() + " couldn't start because no source of character matrices was obtained.");
		return true;
	}

	/*.................................................................................................................*/
	public void setData() {
			matrixSourceTask.initialize(currentTaxa);
			MCharactersDistribution observedStates = matrixSourceTask.getCurrentMatrix(currentTaxa);
			CharacterData d = observedStates.getParentData();
			if (d instanceof MolecularData)
				data = (MolecularData)d;
			else
				data=null;
		
	}
	/*.................................................................................................................*/
	public void setTableAndTaxa(MesquiteTable table, Taxa taxa){
		deleteMenuItem(mss2);
		mss2 = addMenuItem("Move Numbers from GenBank/FASTA Taxon Name", makeCommand("moveNumbersFromName", this));
		if (this.taxa != null)
			this.taxa.removeListener(this);
		this.taxa = taxa;
		if (this.taxa != null)
			this.taxa.addListener(this);
		if (taxa != currentTaxa || data == null ) {
			currentTaxa = taxa;
			setData();
		}
		this.table = table;
	}
	/** Returns whether or not it's appropriate for an employer to hire more than one instance of this module.  
 	If false then is hired only once; second attempt fails.*/
	public boolean canHireMoreThanOnce(){
		return true;
	}
	/*.................................................................................................................*/
	/** Generated by an employee who quit.  The MesquiteModule should act accordingly. */
	public void employeeQuit(MesquiteModule employee) {
		if (employee == matrixSourceTask)  // character source quit and none rehired automatically
			iQuit();
	}
	/*.................................................................................................................*/
	public void employeeParametersChanged(MesquiteModule employee, MesquiteModule source, Notification notification) {
		setData();
		super.employeeParametersChanged(employee, source, notification);
	}
	/*.................................................................................................................*/
	public Snapshot getSnapshot(MesquiteFile file) { 
		Snapshot temp = new Snapshot();
		temp.addLine("getMatrixSource", matrixSourceTask);
		return temp;
	}
	MesquiteInteger pos = new MesquiteInteger();
	/*.................................................................................................................*/
	public Object doCommand(String commandName, String arguments, CommandChecker checker) {
		if (checker.compare(this.getClass(), "Returns the matrix source", null, commandName, "getMatrixSource")) {
			return matrixSourceTask;
		}
		else if (checker.compare(this.getClass(), "Acquires GenBank numbers from imported GenBank taxon names", null, commandName, "moveNumbersFromName")) {
			moveNumberFromGenBankTaxonName();
			return null;
		}
		else return  super.doCommand(commandName, arguments, checker);
	}
	/*.................................................................................................................*/
	private void moveNumberFromGenBankTaxonName() {
			if (table !=null && taxa!=null) {
				boolean changed=false;
				String id = "";
				Parser parser = new Parser();
				parser.setWhitespaceString("|");
				if (employer!=null && employer instanceof ListModule) {
					int c = ((ListModule)employer).getMyColumn(this);
					for (int i=0; i<taxa.getNumTaxa(); i++) {
						if (table.isCellSelectedAnyWay(c, i)) {
							id = taxa.getName(i);
							parser.setString(id);
							String  token = parser.getFirstToken();
							while (token!=null && !token.equalsIgnoreCase("gb") && !StringUtil.blank(token)){
								token = parser.getNextToken();
							}
							if (token!= null && token.equalsIgnoreCase("gb")){
								token = parser.getNextToken();
								if (token.indexOf(".")>=0) {
									token = token.substring(0,token.indexOf("."));
									if (!StringUtil.blank(token)){
										setString(i,token);
										if (!changed)
											outputInvalid();
										changed = true;
									}
								}
							}
						}
					}
				}

//				if (changed)
//					data.notifyListeners(this, new Notification(MesquiteListener.NAMES_CHANGED)); //TODO: bogus! should notify via specs not data???
				outputInvalid();
				parametersChanged();

			}
		
	}
	/*.................................................................................................................*/
	public String getTitle() {
		return "GenBank Number";
	}
	public String getStringForTaxon(int it){
		if (data==null || taxa==null)
			return "-";
		Taxon taxon = data.getTaxa().getTaxon(it);
		Associable tInfo = data.getTaxaInfo(false);
		if (tInfo != null && taxon != null) {
			return (String)tInfo.getAssociatedObject(MolecularData.genBankNumberRef, it);
		}
		return "-";
	}
	/*...............................................................................................................*/
	/** returns whether or not a cell of table is editable.*/
	public boolean isCellEditable(int row){
		return true;
	}
	/*...............................................................................................................*/
	/** for those permitting editing, indicates user has edited to incoming string.*/
	public void setString(int row, String s){
		if (data==null || taxa==null)
			return;
		Taxon taxon = data.getTaxa().getTaxon(row);
		Associable tInfo = data.getTaxaInfo(true);
		if (tInfo != null && taxon != null) {
			tInfo.setAssociatedObject(MolecularData.genBankNumberRef, row, s);
		}
	}
	public boolean useString(int ic){
		return true;
	}

	public String getWidestString(){
		return "8888888888888  ";
	}
	/*.................................................................................................................*/
	public String getName() {
		return "GenBank Number";
	}
	/*.................................................................................................................*/
	public boolean isPrerelease(){
		return false;  
	}
	/*.................................................................................................................*/
	/** returns the version number at which this module was first released.  If 0, then no version number is claimed.  If a POSITIVE integer
	 * then the number refers to the Mesquite version.  This should be used only by modules part of the core release of Mesquite.
	 * If a NEGATIVE integer, then the number refers to the local version of the package, e.g. a third party package*/
	public int getVersionOfFirstRelease(){
		return 273;  
	}
	/*.................................................................................................................*/
	/** returns whether this module is requesting to appear as a primary choice */
	public boolean requestPrimaryChoice(){
		return true;  
	}

	/*.................................................................................................................*/
	/** returns an explanation of what the module does.*/
	public String getExplanation() {
		return "Lists the GenBank accession number of a sequence in a matrix." ;
	}
}
